package com.gitee.sop.layui.adminserver.entrance.bo;

import com.gitee.sop.layui.adminserver.entrance.manager.ServiceContextHolder;
import com.gitee.sop.layui.adminserver.module.background.admin.entity.SysApplication;
import com.gitee.sop.layui.adminserver.module.base.error.ServiceInterruptionException;
import com.gitee.sop.layui.adminserver.module.base.util.ObjectUtil;
import com.gitee.sop.layui.adminserver.plugins.shiro.ShiroUtil;
import lombok.Getter;
import lombok.experimental.Accessors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 业务上下文
 *
 * @author: huwei
 * @date: 2020/4/1 10:16
 * @version: 1.0.0
 */
@Accessors(chain = true)
public class ServiceContext {
    /**
     * 请求客户端ip地址
     */
    @Getter
    private String clientIp;
    /**
     * 请求进入时间 ,毫秒
     */
    @Getter
    private long enterTime;
    /**
     * 请求体
     */
    @Getter
    private HttpServletRequest request;
    /**
     * 返回体
     */
    @Getter
    private HttpServletResponse response;

    public ServiceContext(String clientIp, HttpServletRequest request, HttpServletResponse response) {
        this.clientIp = clientIp;
        this.request = request;
        this.response = response;
        this.enterTime = System.currentTimeMillis();
    }

    public static ServiceContext me() {
        return ServiceContextHolder.getContext();
    }


    public <T> boolean isLogin(Class<? extends T> cls) {
        try {
            return ShiroUtil.isLogin(cls);
        } catch (Throwable throwable) {
            //防止Shiro 没有初始化异常
        }
        return false;
    }

    /**
     * 获取当前登录用户
     *
     * @param cls 用户对象类类型
     * @param <T> 用户对象实例
     * @return 存在，返回用户对象实例；反之，null
     */
    public <T> T getUser(Class<? extends T> cls) {
        try {
            return ShiroUtil.getUser(cls);
        } catch (Throwable throwable) {
            //防止Shiro 没有初始化异常
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 获取当前登录用户
     *
     * @param cls 用户对象类类型
     * @param <T> 用户对象实例
     * @return 存在，返回用户对象实例； 反之，抛出 com.wlx.visting.framework.error.ServiceInterruptionException异常
     */
    public <T> T checkedUserAndGet(Class<? extends T> cls) {
        return checkedUserAndGet(cls, ServiceInterruptionException.fail(401, "用户未登录"));
    }

    /**
     * 获取当前登录用户
     *
     * @param cls 用户对象类类型
     * @param <T> 用户对象实例
     * @return 存在，返回用户对象实例； 反之，抛出 指定的运行时异常
     */
    public <T> T checkedUserAndGet(Class<? extends T> cls, RuntimeException error) {
        T t = getUser(cls);
        if (t == null) {
            throw error;
        }
        return t;
    }

    public ServiceContext setRelationApplication(List<SysApplication> sysApplicationList) {
        try {
            ShiroUtil.setSessionAttr("relationApplication", sysApplicationList);
        } catch (Throwable e) {
            //防止shiro不可用异常
        }
        return this;
    }

    public List<SysApplication> getRelationApplication() {
        try {
            return ShiroUtil.getSessionAttr("relationApplication");
        } catch (Throwable e) {
            //防止shiro不可用异常
        }
        return null;
    }

    public ServiceContext setCurrentApplication(SysApplication sysApplication) {
        try {
            ShiroUtil.setSessionAttr("currentApplication", sysApplication);
        } catch (Throwable e) {
            //防止shiro不可用异常
        }
        return this;
    }

    public SysApplication getCurrentApplication() {
        return new SysApplication().setAppId("4c79c90b04de41e0a98676a85cc5963d").setName("后台系统").setDescription("用于规避多应用问题");
    }

    public List<Map<String, Object>> desensitizationAllApplicationAndGet() {
        return getRelationApplication().stream().collect(ArrayList::new, (res, ele) -> res.add(ObjectUtil.toMapEx(ele, "secretKey")), (l, r) -> {
        });
    }

    public Map<String, Object> desensitizationCurrentApplicationAndGet() {
        return ObjectUtil.toMapEx(getCurrentApplication(), "secretKey");
    }

    public SysApplication getApplicationByAppId(String appId) {
        List<SysApplication> list = getRelationApplication();
        for (int i = 0; i < list.size(); ++i) {
            if (list.get(i).getAppId().equals(appId)) {
                return list.get(i);
            }
        }
        return null;
    }

    public SysApplication getApplicationById(int id) {
        List<SysApplication> list = getRelationApplication();
        for (int i = 0; i < list.size(); ++i) {
            if (list.get(i).getId() == id) {
                return list.get(i);
            }
        }
        return null;
    }
}
